#include <iostream>
#include <atomic>
#include <thread>
#include <mutex>
#include <condition_variable>
#include "common.h"

namespace ATOMIC_DAY27
{
    /*
        C++中的atomic是用于实现原子操作的类模板，它位于头文件中。原子操作是指在多线程环境下，一个操作是不可分割的，不会被其他线程打断。
        atomic提供了一种简单、安全的方式来进行原子操作，避免了使用锁和互斥量等复杂的同步机制。

        atomic支持以下几种类型的数据：

        整数类型（如int、long、short、char等）
        指针类型
        用户自定义类型
    */

    std::atomic<int> count(0); // 定义一个原子整数变量count，初始值为0
    void increase() {
        for (int i = 0; i < 10000; ++i) {
            count.fetch_add(1, std::memory_order_relaxed); // 以relaxed内存序增加count的值
        }
    }

};

namespace NORMAL_DAY27
{
    /*
        C++11中的条件变量（std::condition_variable）是一种同步原语，用于在多线程环境中实现线程间的同步。
        它允许一个或多个线程等待某个条件成立，而另一个线程则负责唤醒等待的线程。
    */
    int count = 0;

    void increase() {
        for (int i = 0; i < 10000; ++i) {
            count++;
        }
    }
};

namespace CONDITION_VARIABLE_DAY27
{
    
    std::mutex mtx; // 互斥锁
    std::condition_variable cv; // 条件变量
    bool ready = false; // 条件变量的条件

    void print_id(int id) {
        std::unique_lock<std::mutex> lck(mtx);
        while (!ready) { // 如果条件不成立，等待
            cv.wait(lck); // 释放互斥锁并等待条件变量
        }
        // 当条件成立时，执行以下操作
        std::cout << "thread " << id << std::endl;
    }

    void go() {
        std::unique_lock<std::mutex> lck(mtx);
        ready = true; // 修改条件变量的条件
        cv.notify_all(); // 唤醒所有等待的线程
    }

};



int main() {

    {
        __LOG__("atomic");
        using namespace ATOMIC_DAY27;
        std::thread t1(increase); // 创建一个线程t1执行increase函数
        std::thread t2(increase); // 创建一个线程t2执行increase函数

        t1.join(); // 等待线程t1执行完毕
        t2.join(); // 等待线程t2执行完毕

        std::cout << "count: " << count << std::endl; // 输出count的值
    }

    {
        __LOG__("normal");
        using namespace NORMAL_DAY27;
        std::thread t1(increase); // 创建一个线程t1执行increase函数
        std::thread t2(increase); // 创建一个线程t2执行increase函数

        t1.join(); // 等待线程t1执行完毕
        t2.join(); // 等待线程t2执行完毕

        std::cout << "count: " << count << std::endl; // 输出count的值
    }

    {
        __LOG__("condition_variable");
        using namespace CONDITION_VARIABLE_DAY27;

        std::thread threads[10];
        // 启动10个线程
        for (int i = 0; i < 10; ++i)
            threads[i] = std::thread(print_id, i);

        std::cout << "10 threads ready to race...";
        go(); // 修改条件变量的条件并唤醒所有等待的线程

        for (auto& th : threads) th.join(); // 等待所有线程结束
    }
    

    return 0;
}
